import React, { useContext, useEffect, useMemo, useState } from 'react';
import { HandleStyles, Position, Rnd, Size } from '../Rnd';
import { StoreActionType } from '../../store/module';
import { StoreModuleData } from '../../modules/TypeConstraints';
import { ModuleTypeClassMap } from '../../modules/config';
import { TextModuleData } from '../../modules/Text/moduleClass';
import {
  ApexAngleHandleStyles,
  getEnableByResizeAxis,
  LineHandleStyles,
  ResizeHandleComponent,
} from './config';
import StyleModule from './style.module.less';

import { MAIN_COLOR } from '@/Editor/config';
import { EditorContext } from '@/Editor';

export interface RndRefMap {
  [key: string]: Rnd | null;
}
export interface BaseModuleProps {
  // module 数据
  moduleData: StoreModuleData;
  onDragStart?: (
    onDragModuleDataList: StoreModuleData[],
    dragModuleDataId: string,
  ) => void;
  onDrag?: (
    onDragModuleDataList: StoreModuleData[],
    dragModuleDataId: string,
  ) => void;
  onDragEnd?: () => void;
}

const RndModule: React.FC<BaseModuleProps> = ({
  moduleData,
  onDragStart,
  onDrag,
  onDragEnd,
}) => {
  const { storeState, dispatch } = useContext(EditorContext);
  const { selectModuleDataIds, moduleDataList } = storeState;
  const isActive = selectModuleDataIds.includes(moduleData.id);

  const { type: moduleType, props: propsData, id: moduleId } = moduleData;
  const { left, top, width, height } = propsData;
  const rotate = (propsData as unknown as TextModuleData['props']).rotate || 0;
  // module类型的"原型"
  const moduleClass = ModuleTypeClassMap[moduleType];
  const {
    viewComponent: ViewComponent,
    resizeAxis,
    lockAspectRatio,
  } = moduleClass;

  // 拖拽锚点的样式
  const resizeHandleStyles: HandleStyles = {
    ...ApexAngleHandleStyles,
    ...LineHandleStyles,
  };

  // 获取能够渲染的锚点
  const enableResizing = useMemo(
    () => getEnableByResizeAxis(resizeAxis),
    [resizeAxis],
  );

  // 选择元素
  function handleSelectModule(event: React.MouseEvent<Element, MouseEvent>) {
    event.stopPropagation();
    event.nativeEvent.stopPropagation();
    // 非激活状态
    if (!isActive) {
      // 多选
      const isNotReset = event.shiftKey || event.ctrlKey || event.metaKey;
      dispatch?.({
        type: StoreActionType.UpdateSelectModuleDataIds,
        payload: {
          selectModuleDataIds: [moduleData.id],
          reset: !isNotReset,
        },
      });
    }
  }

  const [realTimePosition, setRealTimePosition] = useState<Position>();
  const [realTimeSize, setRealTimeSize] = useState<Size>();

  return (
    <Rnd
      lockAspectRatio={lockAspectRatio}
      id={moduleId}
      position={{ left, top }}
      size={{ width, height }}
      rotate={rotate}
      // 激活的样式
      style={{
        zIndex: propsData.zIndex,
        outlineWidth: 1,
        outlineStyle: 'dashed',
        outlineColor: isActive ? MAIN_COLOR : 'transparent',
        // borderWidth: 1,
        // borderStyle: 'dashed',
        // borderColor: isActive ? MAIN_COLOR : 'transparent',
      }}
      resizeHandleStyles={resizeHandleStyles}
      // 可操控的点位，只有在激活的时候才显示
      enableResizing={isActive && enableResizing}
      // 自定义 四边中间 变换 组件
      resizeHandleComponent={ResizeHandleComponent}
      // rnd 默认最小为 10
      minWidth={1}
      minHeight={1}
      bounds="parent"
      // 阻止时间冒泡、选中当前元素
      onResizeStart={(event, dir, delta) => {
        event.stopPropagation();
        event.nativeEvent.stopPropagation();
        setRealTimeSize({ ...delta.size });
      }}
      // 变换时，实时更新组件 位置和大小
      onResize={(event, dir, delta) => {
        setRealTimeSize({ ...delta.size });
      }}
      // 更新module大小和位置信息
      onResizeStop={(e, direction, delta) => {
        setRealTimeSize(undefined);
        const { size, position } = delta;
        dispatch?.({
          type: StoreActionType.UpdateModuleDataList,
          payload: {
            moduleDataList: [
              {
                id: moduleData.id,
                props: { ...position, ...size },
              },
            ],
            merge: true,
          },
        });
      }}
      /* 处理移动 start */
      onDragStart={(event, delta, position) => {
        setRealTimePosition({ ...position });
        // 判断是否聚焦元素
        handleSelectModule(event);
        onDragStart?.(moduleDataList, moduleData.id);
      }}
      // 其它组件也需要更新
      onDrag={(event, delta, position) => {
        setRealTimePosition({ ...position });
      }}
      // 更新所有的数据
      onDragStop={(event, delta, position) => {
        setRealTimePosition(undefined);

        // 批量更新组件信息
        dispatch?.({
          type: StoreActionType.UpdateModuleDataList,
          payload: {
            moduleDataList: [
              {
                ...moduleData,
                props: {
                  ...moduleData.props,
                  ...position,
                },
              },
            ],
            merge: true,
          },
        });
        onDragEnd?.();
      }}
    >
      <ViewComponent moduleData={moduleData as never} />
      {(() => {
        if (realTimePosition) {
          return (
            <div className={StyleModule['position-size-info']}>
              <span className="show-left">{`T: ${parseInt(
                `${realTimePosition.top}`,
              )}`}</span>
              <span className="show-top">{`L: ${parseInt(
                `${realTimePosition.left}`,
              )}`}</span>
            </div>
          );
        }

        if (realTimeSize) {
          return (
            <div className={StyleModule['position-size-info']}>
              <span className="show-left">{`H: ${parseInt(
                `${realTimeSize.height}`,
              )}`}</span>
              <span className="show-top">{`W: ${parseInt(
                `${realTimeSize.width}`,
              )}`}</span>
            </div>
          );
        }
      })()}
    </Rnd>
  );
};

export default RndModule;
